package shooter;

import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.AlphaComposite;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Cursor;
import java.awt.Font;
import java.awt.Graphics2D;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import javax.swing.ImageIcon;

import shooter.handler.GameEventListener;
import shooter.handler.InputHandler;
import shooter.maps.GameMap;
import shooter.models.Player;
import shooter.models.Shot;
import shooter.models.Sprite;
import shooter.models.Wall;
import shooter.network.MovementMessage;
import shooter.network.StateMessage;
import shooter.network.crossClient;
import shooter.network.crossServer;
import shooter.sound.SoundCache;
import shooter.xml.Xmlschreiber;

/**
 * Shooter is the main game class. If it is called a frame with 
 * the game in it appears. Everything will be pre configured.
 * 
 * @author Michail Tausch
 */
public class Shooter implements GameEventListener {

	int HEIGHT = 0;
	int WIDTH = 0;

	int rowCount = 0;

	int roundTime = 0;
	int time = 3;
	int timeToNextRound = 0;
	boolean timeToNextRoundHelp = false;

    public int playerIndex = 0;
	int statsTeamRot = 0;
	int statsTeamBlau = 0;
	int dispose = 0;

	long count = 0;
	long ping = 0;
	long pingStart = 0;
//	long pings[][];

	int id = 1;

	GUI gui;
	Canvas cav;

	boolean game = true;
	boolean stats = false;
	boolean gameStop = false;
	boolean gameStart = false;
	boolean fF = false;
	boolean sM = false;
	boolean fB = false;
	boolean replay = false;
	boolean start = true;
	boolean newGame = false;
	boolean collison = true;

	int mapVector[][];

	Graphics2D g;

	List<Sprite> shots = new LinkedList<Sprite>();
	List<Sprite> removeShots = new LinkedList<Sprite>();
	List<Sprite> kisten = new LinkedList<Sprite>();
	List<Player> players = new LinkedList<Player>();
	List<Integer>clientShots = new LinkedList<Integer>();

	List<String> playerRed = new LinkedList<String>();
	List<String> playerBlue = new LinkedList<String>();

	List<Player> plist = null;
	List<Sprite> slist = null;
	
	SoundCache soundCache = new SoundCache();

	AudioClip[] weaponSounds;
	AudioClip[] spreeSounds;
	AudioClip[] tWins;
	AudioClip[] ctWins;
	AudioClip[] death;
	AudioClip[] sounds;

	AudioClip Sound;

	String untergrund = null;

	int spawnRot[][];
	int spawnBlau[][];
	private crossServer crossServer;
	private crossClient crossClient;
	
	/**
	 * Creates a shooter object.
	 * 
	 * @param file
	 * @param roundTime
	 * @param playerRed
	 * @param playerBlue
	 * @param fF
	 * @param sM
	 * @param crossServer
	 * @param crossClient
	 * @param replay
	 * @throws IOException
	 * @throws URISyntaxException
	 */
	public Shooter(File file, int roundTime, List<String> playerRed,
			List<String> playerBlue, boolean fF, boolean sM, crossServer crossServer, crossClient crossClient) throws IOException, URISyntaxException {

		this.playerRed = playerRed;
		this.playerBlue = playerBlue;
		this.fF = fF;
		this.sM = sM;
		this.roundTime = roundTime;
		this.crossServer = crossServer;
		this.crossClient=crossClient;

		spawnRot = new int[10][2];

		for (int x = 0; x < spawnRot.length; x++) {
			for (int y = 0; y < spawnRot[x].length; y++) {
				spawnRot[x][y] = 0;
			}
		}

		spawnBlau = new int[10][2];

		for (int x = 0; x < spawnBlau.length; x++) {
			for (int y = 0; y < spawnBlau[x].length; y++) {
				spawnBlau[x][y] = 0;
			}
		}

		FileReader fr = new FileReader(file);
		BufferedReader br = new BufferedReader(fr);

		String zahl = br.readLine();
		if (zahl.equals("1")) {
			setHEIGHT(600);
			setWIDTH(600);
			setRowCount(20);
		} else if (zahl.equals("2")) {
			setHEIGHT(750);
			setWIDTH(750);
			setRowCount(25);
		} else if (zahl.equals("3")) {
			setHEIGHT(900);
			setWIDTH(900);
			setRowCount(30);
		}		

		gui = new GUI(WIDTH, HEIGHT, this);
		gui.getFrame().setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));

		String map = null;

		this.mapVector = new int[rowCount][rowCount];
//		this.pings = new long [10][2];
//		
//		for (int x = 0; x < pings.length; x++) {
//			for (int y = 0; y < pings[x].length; y++) {
//				pings[x][y] = 999;
//			}
//		}
		
		int indexRot = 0;
		String teamRot = br.readLine();
		for (int k = 0; k < Integer.parseInt(teamRot); k++) {
			String tempRot = br.readLine();
			String[] coordinaten = tempRot.split("-");
			int x = Integer.parseInt(coordinaten[0]);
			int y = Integer.parseInt(coordinaten[1]);
			spawnRot[indexRot][0] = x;
			spawnRot[indexRot][1] = y;
			indexRot++;
		}

		int indexBlau = 0;
		String teamBlau = br.readLine();
		for (int k = 0; k < Integer.parseInt(teamBlau); k++) {
			String tempBlau = br.readLine();
			String[] coordinaten = tempBlau.split("-");
			int x = Integer.parseInt(coordinaten[0]);
			int y = Integer.parseInt(coordinaten[1]);
			spawnBlau[indexBlau][0] = x;
			spawnBlau[indexBlau][1] = y;
			indexBlau++;
		}

		try {
			map = GameMap.readFileAsString(file);
		} catch (IOException e) {
			e.printStackTrace();
		}
		map = map.substring(map.indexOf(',') - 1);
		String[] mapLines = map.split(",");
		int[] gameMap = new int[mapLines.length];

		for (int i = 0; i < mapLines.length; i++) {
			mapLines[i] = mapLines[i].trim();
			gameMap[i] = Integer.parseInt(mapLines[i]);
		}
		this.mapVector = GameMap.flatToTabularArray(gameMap, rowCount);

		weaponSounds = new AudioClip[11];
		spreeSounds = new AudioClip[7];
		tWins = new AudioClip[14];
		ctWins = new AudioClip[12];
		death = new AudioClip[3];
		sounds = new AudioClip[2];

		for (int i = 0; i < 8; i++) {
			try {
				Sound =
						Applet.newAudioClip(new URL(getClass().getResource(
								Einstellungen.getSoundsWeaponsFolderPath() + i
										+ ".wav").toString()));
			} catch (MalformedURLException e) {
				System.out
						.println("Audiofile Error: Malformed URI (file not found)");
			}
			weaponSounds[i] = Sound;
		}

		for (int i = 0; i < 7; i++) {
			try {
				Sound =
						Applet.newAudioClip(new URL(getClass().getResource(
								Einstellungen.getSoundsSpreeFolderPath() + i
										+ ".wav").toString()));
			} catch (MalformedURLException e) {
				System.out
						.println("Audiofile Error: Malformed URI (file not found)");
			}
			spreeSounds[i] = Sound;
		}

		for (int i = 0; i < 13; i++) {
			try {
				Sound =
						Applet.newAudioClip(new URL(getClass().getResource(
								Einstellungen.getSoundsTWinsFolderPath() + i
										+ ".wav").toString()));
			} catch (MalformedURLException e) {
				System.out
						.println("Audiofile Error: Malformed URI (file not found)");
			}
			tWins[i] = Sound;
		}

		for (int i = 0; i < 3; i++) {
			try {
				Sound =
						Applet.newAudioClip(new URL(getClass().getResource(
								Einstellungen.getSoundsDeathFolderPath() + i
										+ ".wav").toString()));
			} catch (MalformedURLException e) {
				System.out
						.println("Audiofile Error: Malformed URI (file not found)");
			}
			death[i] = Sound;
		}

		for (int i = 0; i < 12; i++) {
			try {
				Sound =
						Applet.newAudioClip(new URL(getClass().getResource(
								Einstellungen.getSoundsCTWinsFolderPath() + i
										+ ".wav").toString()));
			} catch (MalformedURLException e) {
				System.out
						.println("Audiofile Error: Malformed URI (file not found)");
			}
			ctWins[i] = Sound;
		}

		for (int i = 0; i < 2; i++) {
			try {
				Sound =
						Applet.newAudioClip(new URL(getClass().getResource(
								Einstellungen.getSoundsFolderPath() + i
										+ ".wav").toString()));
			} catch (MalformedURLException e) {
				System.out
						.println("Audiofile Error: Malformed URI (file not found)");
			}
			sounds[i] = Sound;
		}

		new Thread() {
			@Override
			public void run() {
				gameLoop();
			}
		}.start();

	}
	
	/**
	 * Starts the gaming loop. It calculates everything and sends StateMessage 
	 * to all clients.
	 */
	public void gameLoop() {

		g = gui.getGraphics2D();
		Iterator<Sprite> kistenMove;
		Iterator<Player> iteratorPlayer;
		synchronized (players) {

			Iterator<String> addNames = playerRed.iterator();
			int loc = 0;
			while (addNames.hasNext()) {
				String name = addNames.next();
				Player player =
						new Player(id - 1, 1, spawnRot[loc][0] * 30,
								spawnRot[loc][1] * 30, name, sM);
				this.newPlayer(player);
				id++;
				loc++;
			}

			addNames = playerBlue.iterator();
			loc = 0;
			while (addNames.hasNext()) {
				String name = addNames.next();
				Player player =
						new Player(id - 1, 2, spawnBlau[loc][0] * 30,
								spawnBlau[loc][1] * 30, name, sM);
				this.newPlayer(player);
				id++;
				loc++;
			}

			int i = 0;
			int j = 0;
			for (int k = 0; k < rowCount; k++) {
				for (int l = 0; l < rowCount; l++) {
					if (this.mapVector[k][l] == 1) {
						Wall wall = new Wall(i, j, 1);
						this.newWall(wall);
					} else if (this.mapVector[k][l] == 2) {
						Wall wall = new Wall(i, j, 2);
						this.newWall(wall);
					} else if (this.mapVector[k][l] == 3) {
						Wall wall = new Wall(i, j, 3);
						this.newWall(wall);
					}
					j = j + 30;
				}
				i = i + 30;
				j = 0;
			}

			paintMap(g);

			kistenMove = kisten.iterator();
			while (kistenMove.hasNext()) {
				Sprite kiste = kistenMove.next();
				kiste.move(0);
				kiste.draw(g);
			}

			iteratorPlayer = players.iterator();
			while (iteratorPlayer.hasNext()) {
				Player player = iteratorPlayer.next();
				player.move(0);
				if (player.getTeam() == 1) {
					player.setAngle(180);
				}
			}

			int help = 0;
			iteratorPlayer = players.iterator();
			while (iteratorPlayer.hasNext()) {
				Player player = iteratorPlayer.next();
				if (player.getName().equals(Xmlschreiber.getPlayerName())) {
					playerIndex = help;
				}
				help++;
			}			
		}
		
		gui.getCanvas().setFocusTraversalKeysEnabled(false);
		gui.getCanvas().requestFocus();
		if (this.crossServer != null) {
			gui.getCanvas().addKeyListener(
					new InputHandler(playerIndex, this, null));
		} else {
			gui.getCanvas().addKeyListener(
					new InputHandler(playerIndex, this, crossClient));
		}

		while (game) {
			long start = System.currentTimeMillis();

			synchronized (players) {
				if (gameStop == true || crossClient != null) {
					iteratorPlayer = players.iterator();
					while (iteratorPlayer.hasNext()) {
						Player player = iteratorPlayer.next();
						player.doActions(20, this);
					}
				}	
				StateMessage ms = calculateState();				
				if (crossServer != null) {		
					this.setState(ms);
					this.crossServer.sendMessage(ms);
				}
				plist = new ArrayList<Player>(this.players);
				slist = new ArrayList<Sprite>(this.shots);
			}

			iteratorPlayer = plist.iterator();
			while (iteratorPlayer.hasNext()) {
				Player player = iteratorPlayer.next();
				refreshObjects(g, player, slist);
			}
			
			if(crossServer == null){
				refreshHittenObject(g, plist.get(playerIndex));
			}

			iteratorPlayer = plist.iterator();
			while (iteratorPlayer.hasNext()) {
				Player player = iteratorPlayer.next();
				dealWithAmo(player, g);
			}

			setWeaponCounts(plist.get(playerIndex), g);
			setHP(plist.get(playerIndex), g);

			setTime(time, g);

			iteratorPlayer = plist.iterator();
			while (iteratorPlayer.hasNext()) {
				Player player = iteratorPlayer.next();
				player.draw(g);
			}

			drawPlayerArrow(plist.get(playerIndex), g);

			paintStats(g);

			gui.showStrategyGraphics();
			
			if(newGame){
				forceNewRound(plist);
				newGame=false;
			}
			
			long mid = System.currentTimeMillis();

			if ((mid - start) < 15) {
				try {
					Thread.sleep(15 - (mid - start));
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}

			long end = System.currentTimeMillis();
			
//			if (crossServer!=null){
//				ping = ping + (end - start);
//				if(ping >= 2000){
//					PingMessage pM = new PingMessage();
//					pingStart = System.currentTimeMillis();
//					ping = 0;
//					crossServer.sendMessage(pM);
//				}				
//			}

			count = count + (end - start);
			if (count >= 1000) {
				if(crossServer!=null){
					time--;
				}				
				count = 0;
			}
		}
	}
	
	/**
	 * Displays the round time on the gaming screen. 
	 * @param time
	 * @param g
	 */
	public void setTime(int time, Graphics2D g) {
		if (time < 0) {
			return;
		}
		if (time >= 60) {
			g.drawImage(Images.zahlen[1], WIDTH / 2 - 30, HEIGHT - 80, null);
			g.drawImage(Images.zahlen[10], WIDTH / 2 - 15, HEIGHT - 70, null);
			if (time - 60 >= 10) {
				g.drawImage(Images.zahlen[Integer.parseInt(Integer.toString(
						time - 60).substring(0, 1))], WIDTH / 2 - 5,
						HEIGHT - 80, null);
				g.drawImage(Images.zahlen[Integer.parseInt(Integer.toString(
						time - 60).substring(1, 2))], WIDTH / 2 + 20,
						HEIGHT - 80, null);
			} else {
				g.drawImage(Images.zahlen[0], WIDTH / 2 - 5, HEIGHT - 80, null);
				g.drawImage(Images.zahlen[time - 60], WIDTH / 2 + 20,
						HEIGHT - 80, null);
			}
		} else {
			if (time < 16) {
				g.drawImage(Images.zahlenRot[0], WIDTH / 2 - 40, HEIGHT - 80,
						null);
				g.drawImage(Images.zahlenRot[10], WIDTH / 2 - 15, HEIGHT - 70,
						null);
				if (time >= 10) {
					g.drawImage(Images.zahlenRot[Integer.parseInt(Integer
							.toString(time).substring(0, 1))], WIDTH / 2 - 5,
							HEIGHT - 80, null);
					g.drawImage(Images.zahlenRot[Integer.parseInt(Integer
							.toString(time).substring(1, 2))], WIDTH / 2 + 20,
							HEIGHT - 80, null);
				} else {
					g.drawImage(Images.zahlenRot[0], WIDTH / 2 - 5,
							HEIGHT - 80, null);
					g.drawImage(Images.zahlenRot[time], WIDTH / 2 + 20,
							HEIGHT - 80, null);
				}
			} else {
				g
						.drawImage(Images.zahlen[0], WIDTH / 2 - 40,
								HEIGHT - 80, null);
				g.drawImage(Images.zahlen[10], WIDTH / 2 - 15, HEIGHT - 70,
						null);
				if (time >= 10) {
					g.drawImage(Images.zahlen[Integer.parseInt(Integer
							.toString(time).substring(0, 1))], WIDTH / 2 - 5,
							HEIGHT - 80, null);
					g.drawImage(Images.zahlen[Integer.parseInt(Integer
							.toString(time).substring(1, 2))], WIDTH / 2 + 20,
							HEIGHT - 80, null);
				} else {
					g.drawImage(Images.zahlen[0], WIDTH / 2 - 5, HEIGHT - 80,
							null);
					g.drawImage(Images.zahlen[time], WIDTH / 2 + 20,
							HEIGHT - 80, null);
				}
			}
		}
	}
	
	/**
	 * Displays the health points of a player on the game screen.
	 * @param player
	 * @param g
	 */
	public void setHP(Player player, Graphics2D g) {
		int m = String.valueOf(player.getHp()).length();

		int k = 50;
		int l = WIDTH - 80;

		if (m == 3) {
			g.drawImage(Images.zahlen[Integer.parseInt(Integer.toString(
					player.getHp()).substring(0, 1))], k + 10, l, null);
			g.drawImage(Images.zahlen[Integer.parseInt(Integer.toString(
					player.getHp()).substring(1, 2))], k + 25, l, null);
			g.drawImage(Images.zahlen[Integer.parseInt(Integer.toString(
					player.getHp()).substring(2, 3))], k + 50, l, null);
		} else if (m == 2) {
			if (player.getHp() > 26) {
				g.drawImage(Images.zahlen[Integer.parseInt(Integer.toString(
						player.getHp()).substring(0, 1))], k + 25, l, null);
				g.drawImage(Images.zahlen[Integer.parseInt(Integer.toString(
						player.getHp()).substring(1, 2))], k + 50, l, null);
			} else {
				g.drawImage(Images.zahlenRot[Integer.parseInt(Integer.toString(
						player.getHp()).substring(0, 1))], k + 25, l, null);
				g.drawImage(Images.zahlenRot[Integer.parseInt(Integer.toString(
						player.getHp()).substring(1, 2))], k + 50, l, null);
			}
		} else if (m == 1) {
			g.drawImage(Images.zahlenRot[player.getHp()], k + 50, l, null);
		}
	}
	/**
	 * Displays the weapon counts of a player on the game screen.
	 * @param player
	 * @param g
	 */
	public void setWeaponCounts(Player player, Graphics2D g) {
		if (!(player.getWeaponMode() == 0)) {
			int k = WIDTH - 100;
			int l = HEIGHT - 80;
			if (Integer.toString(
					player.getWeaponStuff()[player.getWeaponMode()][1])
					.length() == 2) {
				g.drawImage(Images.zahlen[Integer.parseInt(Integer.toString(
						player.getWeaponStuff()[player.getWeaponMode()][1])
						.substring(0, 1))], k, l, null);
				g.drawImage(Images.zahlen[Integer.parseInt(Integer.toString(
						player.getWeaponStuff()[player.getWeaponMode()][1])
						.substring(1, 2))], k + 25, l, null);
			}
			if (Integer.toString(
					player.getWeaponStuff()[player.getWeaponMode()][1])
					.length() == 1) {
				g.drawImage(Images.zahlen[player.getWeaponStuff()[player
						.getWeaponMode()][1]], k + 25, l, null);
			}

			g.drawImage(Images.zahlen[11], WIDTH - 110, HEIGHT - 80, null);

			k = WIDTH - 163;
			l = HEIGHT - 80;

			if (Integer.toString(
					player.getWeaponStuff()[player.getWeaponMode()][2])
					.length() == 2) {
				g.drawImage(Images.zahlen[Integer.parseInt(Integer.toString(
						player.getWeaponStuff()[player.getWeaponMode()][2])
						.substring(0, 1))], k, l, null);
				g.drawImage(Images.zahlen[Integer.parseInt(Integer.toString(
						player.getWeaponStuff()[player.getWeaponMode()][2])
						.substring(1, 2))], k + 25, l, null);
			}

			if (Integer.toString(
					player.getWeaponStuff()[player.getWeaponMode()][2])
					.length() == 1) {
				g.drawImage(Images.zahlen[player.getWeaponStuff()[player
						.getWeaponMode()][2]], k + 25, l, null);
			}
		}
	}
	
	/**
	 * Checks if a player has to rearm or not and displays the relaod rectangle.
	 * @param player
	 * @param g
	 */
	public void dealWithAmo(Player player, Graphics2D g) {
		if (sM && player.getWeaponStuff()[player.getWeaponMode()][2] == 0) {
			player.reloadTime = player.reloadTime + 0.9;
			if (player.reloadTime >= 50) {
				player.setWeaponStuff(5, 1, 1);
				player.setWeaponStuff(5, 2, 1);
				player.reloadTime = 0;
			}
			return;
		}
		if (player.getWeaponStuff()[player.getWeaponMode()][2] == 0
				&& player.getWeaponStuff()[player.getWeaponMode()][1] > 0) {
			player.setRearm(true);
			g.setColor(Color.BLACK);
			g.drawRect((int) player.getX() - 13, (int) player.getY() - 18, 50,
					12);
			g.setColor(Color.GREEN);
			g.fillRect((int) player.getX() - 12, (int) player.getY() - 17,
					(int) player.reloadTime, 11);
			g.setColor(Color.BLACK);
			g.drawString("reload", (int) player.getX() - 6,
					(int) player.getY() - 7);
			if(crossServer!=null){
				player.reloadTime = player.reloadTime + 0.25;
			}			
			if (player.reloadTime == 50) {
				player.setRearm(false);
				player.rearm();
				player.reloadTime = 0;
			}
			return;
		}
		if (player.isRearm()
				&& player.getWeaponStuff()[player.getWeaponMode()][1] != 0
				&& (player.getWeaponStuff()[player.getWeaponMode()][2] != player
						.getWeaponStuff()[player.getWeaponMode()][3])) {
			if (player.getWeaponStuff()[player.getWeaponMode()][1] > 0) {
				player.setFire(false);
				g.setColor(Color.BLACK);
				g.drawRect((int) player.getX() - 13, (int) player.getY() - 18,
						50, 12);
				g.setColor(Color.GREEN);
				g.fillRect((int) player.getX() - 12, (int) player.getY() - 17,
						(int) player.reloadTime, 11);
				g.setColor(Color.BLACK);
				g.drawString("reload", (int) player.getX() - 6, (int) player
						.getY() - 7);
				if(crossServer!=null){
					player.reloadTime = player.reloadTime + 0.25;
				}
				if (player.reloadTime == 50) {
					player.rearm();
					player.reloadTime = 0;
					player.setRearm(false);
					player.setFire(true);
				}
			}
			return;
		}
		if (player.getWeaponStuff()[player.getWeaponMode()][2] == player
				.getWeaponStuff()[player.getWeaponMode()][3]) {
			player.setRearm(false);
			return;
		}
		player.setRearm(false);
		player.setFire(true);
		return;
	}
	
	/**
	 * Checks the collision of a Player with each Sprite and handles it.
	 * @param player
	 * @param players
	 * @param shots
	 * @param kisten
	 * @param g
	 */
	public void dealWithCollision(Player player, List<Player> players,
			List<Sprite> shots, List<Sprite> kisten, Graphics2D g) {

		Iterator<Sprite> iteratorShots = shots.iterator();
		Iterator<Sprite> iteratorKisten = kisten.iterator();
		Iterator<Player> iteratorPlayer = players.iterator();

		while (iteratorPlayer.hasNext()) {
			Player player2 = iteratorPlayer.next();
			if (player2.collidesWith(player)) {
				if (player2.getId() != player.getId()) {
					double winkel = getCollisionWinkel(player, player2);
					if (winkel > 45 && winkel <= 135) {
						player.setY(player.getLastY());
					} else if ((winkel > 135 && winkel <= 180)
							|| (winkel >= -180 && winkel <= -135)) {
						player.setX(player.getLastX());
					} else if (winkel > -135 && winkel <= -45) {
						player.setY(player.getLastY());
					} else if (winkel > -45 && winkel <= 45) {
						player.setX(player.getLastX());
					}
				}
			}
		}
		
		while (iteratorShots.hasNext()) {
			Sprite shot = iteratorShots.next();
			if (shot.collidesWith(player)) {
				if (player.getId() != shot.getId()) {
					if (fF == true) {
						if (fB == false) {
							spreeSounds[6].play();
							fB = true;
						}
						int newHP =
								player.getHp()
										- players.get(shot.getId())
												.getWeaponStuff()[players.get(
												shot.getId()).getWeaponMode()][5];
						if (newHP == 0 || newHP < 0) {
							player.setHp(0);
							playDeathSound();
							refreshHittenObject(g, player);
							disposePlayer(player);
							removeShots.add(shot);
							player.setFire(false);
							player.setShoot(false);
							if (players.get(shot.getId()).getTeam() == player
									.getTeam()) {
								players.get(shot.getId()).setStatsKills(
										players.get(shot.getId())
												.getStatsKills() - 1);
								players.get(shot.getId()).setSpree(0);
								player
										.setStatsDeaths(player.getStatsDeaths() + 1);
								player.setSpree(0);
							} else {
								players.get(shot.getId()).setStatsKills(
										players.get(shot.getId())
												.getStatsKills() + 1);
								players.get(shot.getId())
										.setSpree(
												players.get(shot.getId())
														.getSpree() + 1);
								playSpreeSound(players.get(shot.getId()));
								player
										.setStatsDeaths(player.getStatsDeaths() + 1);
								player.setSpree(0);
							}
						} else {
							player.setHp(newHP);
							removeShots.add(shot);
							refreshHittenObject(g, player);
						}
					} else {
						if (players.get(shot.getId()).getTeam() == player
								.getTeam()) {
							removeShots.add(shot);
						} else {
							if (fB == false) {
								spreeSounds[6].play();
								fB = true;
							}
							int newHP =	player.getHp()
											- players.get(shot.getId())
													.getWeaponStuff()[players
													.get(shot.getId())
													.getWeaponMode()][5];
							if (newHP == 0 || newHP < 0) {
								player.setHp(0);
								playDeathSound();
								refreshHittenObject(g, player);
								disposePlayer(player);
								removeShots.add(shot);
								player.setFire(false);
								player.setShoot(false);
								players.get(shot.getId()).setStatsKills(
										players.get(shot.getId())
												.getStatsKills() + 1);
								players.get(shot.getId())
										.setSpree(
												players.get(shot.getId())
														.getSpree() + 1);
								playSpreeSound(players.get(shot.getId()));
								player
										.setStatsDeaths(player.getStatsDeaths() + 1);
								player.setSpree(0);
							} else {
								player.setHp(newHP);
								removeShots.add(shot);
								refreshHittenObject(g, player);
							}
						}
					}
				}
			}
		}		

		while (iteratorKisten.hasNext()) {
			Sprite kiste = iteratorKisten.next();
			iteratorShots = shots.iterator();
			while (iteratorShots.hasNext()) {
				Sprite shot = iteratorShots.next();
				if (shot.collidesWith(kiste)) {
					removeShots.add(shot);
					refreshHittenObject(g, kiste);
				}
			}
		}

		iteratorShots = removeShots.iterator();
		while (iteratorShots.hasNext()) {
			Sprite shot = iteratorShots.next();
			shots.remove(shot);
		}

		iteratorKisten = kisten.iterator();
		while (iteratorKisten.hasNext()) {
			Sprite kiste = iteratorKisten.next();
			if (player.collidesWith(kiste)) {
				double winkel = getCollisionWinkel(kiste, player);
				if (winkel > 45 && winkel <= 135) {
					player.setY(player.getLastY());
				} else if ((winkel > 135 && winkel <= 180)
						|| (winkel >= -180 && winkel <= -135)) {
					player.setX(player.getLastX());
				} else if (winkel > -135 && winkel <= -45) {
					player.setY(player.getLastY());
				} else if (winkel > -45 && winkel <= 45) {
					player.setX(player.getLastX());
				}
			}
		}
	}
	/**
	 * Checks whether a gaming round is ending or all players of one
	 * team are death for example. So it calls newRound and a new round starts.
	 * @param player
	 */
	public void checkRound(List<Player> player) {
		if(crossClient!=null){
			if(time==3){
				paintMap(g);
			}
		}
		if (time == -1 && gameStart == false) {
			if(crossServer!=null){
				collison=true;
				time = roundTime;
			}
			if (start) {
				sounds[0].play();
				start = false;
			}

			gameStop = true;
			gameStart = true;
			timeToNextRoundHelp = false;
			
			if (crossServer!=null){
				timeToNextRound = 0;
			}
		}

		if (time == -1 && gameStart == true) {

			boolean teamRed = false;
			boolean teamBlue = false;

			Iterator<Player> iteratorPlayer = player.iterator();
			while (iteratorPlayer.hasNext()) {
				Player player1 = iteratorPlayer.next();
				if (player1.getHp() > 0) {
					if (player1.getTeam() == 1) {
						teamRed = true;
					} else {
						teamBlue = true;
					}
				}
			}

			if (teamBlue && teamRed) {
				soundCache.playSound(sounds[1]);
			}

			newRound(player);
			
			if (crossServer!=null){
				time = 3;
				timeToNextRound = 0;
			}			
			gameStop = false;
			gameStart = false;			
			timeToNextRoundHelp = false;
		}

		boolean teamRed = false;
		boolean teamBlue = false;

		Iterator<Player> iteratorPlayer = player.iterator();
		while (iteratorPlayer.hasNext()) {
			Player player1 = iteratorPlayer.next();
			if (player1.getHp() > 0) {
				if (player1.getTeam() == 1) {
					teamRed = true;
				} else {
					teamBlue = true;
				}
			}
		}

		if ((teamRed == true && teamBlue == false) && !playerRed.isEmpty() && !playerBlue.isEmpty()) {
			if (timeToNextRoundHelp == false) {
				if (crossServer!=null){
					timeToNextRound = time - 5;
				}				
				timeToNextRoundHelp = true;
				Random random = new Random();
				soundCache.playSound(tWins[random.nextInt(13)]);
				if(crossServer!=null){
					statsTeamRot = statsTeamRot + 1;
				}
			}
			if (time == timeToNextRound) {
				if(crossServer!=null){
					collison=false;
				}
				newRound(player);				
				gameStop = false;
				gameStart = false;				
				timeToNextRoundHelp = false;
				if (crossServer!=null){
					time = 3;
					timeToNextRound = 0;
				}				
			}
		}

		if ((teamRed == false && teamBlue == true) && !playerRed.isEmpty() && !playerBlue.isEmpty()) {
			if (timeToNextRoundHelp == false) {
				if (crossServer!=null){
					timeToNextRound = time - 5;
				}	
				timeToNextRoundHelp = true;
				Random random = new Random();
				soundCache.playSound(ctWins[random.nextInt(12)]);
				if(crossServer!=null){
					statsTeamBlau = statsTeamBlau + 1;
				}
			}
			if (time == timeToNextRound) {
				if(crossServer!=null){
					collison=false;
				}
				newRound(player);				
				gameStop = false;
				gameStart = false;				
				timeToNextRoundHelp = false;
				if (crossServer!=null){
					time = 3;
					timeToNextRound = 0;
				}
			}
		}

		if (teamRed == false && teamBlue == false) {
			if (timeToNextRoundHelp == false) {
				if (crossServer!=null){
					timeToNextRound = time - 1;
				}				
				timeToNextRoundHelp = true;
			}
			if (time == timeToNextRound) {
				if(crossServer!=null){
					collison=false;
				}
				soundCache.playSound(sounds[0]);
				newRound(player);				
				gameStop = false;
				gameStart = false;				
				timeToNextRoundHelp = false;
				if (crossServer!=null){
					time = 3;
					timeToNextRound = 0;
				}
			}
		}
	}
	
	/**
	 * Plays the spree sounds.
	 * @param player
	 */
	public void playSpreeSound(Player player) {
		
		if (player.getSpree() == 3) {
			soundCache.playSound(spreeSounds[0]);								
		}
		if (player.getSpree() == 4) {
			soundCache.playSound(spreeSounds[1]);
		}
		if (player.getSpree() == 5) {
			soundCache.playSound(spreeSounds[2]);
		}
		if (player.getSpree() == 6) {
			soundCache.playSound(spreeSounds[3]);
		}
		if (player.getSpree() == 7) {
			soundCache.playSound(spreeSounds[4]);
		}
		if (player.getSpree() > 7) {
			soundCache.playSound(spreeSounds[5]);
		}
	}
	
	/**
	 * Returns the angle of two sprites if they colidate with each other.
	 * @param kiste
	 * @param player
	 * @return
	 */
	public double getCollisionWinkel(Sprite kiste, Player player) {
		double winkel =
				-Math.atan2(player.getY() - kiste.getY(), player.getX()
						- kiste.getX())
						* 180 / Math.PI;
		;
		return winkel;
	}
	
	/**
	 * Removes a death player from the sreen.
	 */
	public void disposePlayer(Player player) {
		player.setX(player.getLastX());
		player.setY(player.getLastY());
		player.setX(1500 + dispose);
		player.setY(1500 + dispose);
		player.setLastX(1500+ dispose);
		player.setLastY(1500 + dispose);
		dispose = dispose + 100;
	}
	
	/**
	 * Plays a death sound if a player dies.
	 */
	public void playDeathSound() {
		Random random = new Random();
		death[random.nextInt(3)].play();
	}
	
	/**
	 * Removes a shot out of the shot list.
	 */
	public void disposeShot(Shot shot) {
		removeShots.add(shot);
	}

	/**
	 * Creates a new shot and plays the shot sound.
	 */
	public void newShot(Shot shot, Player player) {
		shots.add(shot);
		if (sM) {
			soundCache.playSound(weaponSounds[7]);
			clientShots.add(7);
			return;
		}
		if (player.getTeam() == 2) {
			if (player.getWeaponMode() == 1) {
				soundCache.playSound(weaponSounds[5]);
				clientShots.add(5);
				return;
			}
			soundCache.playSound(weaponSounds[player.getWeaponMode()]);
			clientShots.add(player.getWeaponMode());
		}
		if (player.getTeam() == 1) {
			soundCache.playSound(weaponSounds[player.getWeaponMode()]);
			clientShots.add(player.getWeaponMode());
		}
	}
	
	/**
	 * Refreshes the game screen around a player and all shots.
	 * It also draws the shots.
	 * @param g
	 * @param player
	 * @param players
	 * @param shots
	 */
	public void refreshObjects(Graphics2D g, Player player, List<Sprite> shots) {
		int kachelHorizontal = (int) Math.round(player.getX() / 30);
		int kachelVertikal = (int) Math.round(player.getY() / 30);

		for (int c = kachelHorizontal - 2; c < kachelHorizontal + 2; c++) {
			try {
				g.drawImage(Images.images[mapVector[c][kachelVertikal - 2]],
						c * 30, (kachelVertikal - 2) * 30, null);
			} catch (ArrayIndexOutOfBoundsException e) {
			}
			try {
				g.drawImage(Images.images[mapVector[c][kachelVertikal - 1]],
						c * 30, (kachelVertikal - 1) * 30, null);
			} catch (ArrayIndexOutOfBoundsException e) {
			}
			try {
				g.drawImage(Images.images[mapVector[c][kachelVertikal]],
						c * 30, kachelVertikal * 30, null);
			} catch (ArrayIndexOutOfBoundsException e) {
			}
			try {
				g.drawImage(Images.images[mapVector[c][kachelVertikal + 1]],
						c * 30, (kachelVertikal + 1) * 30, null);
			} catch (ArrayIndexOutOfBoundsException e) {
			}
		}

		for (int c = (WIDTH / 30) - 6; c < WIDTH / 30; c++) {
			g.drawImage(Images.images[mapVector[c][(HEIGHT / 30) - 2]], c * 30,
					((HEIGHT / 30) - 2) * 30, null);
			g.drawImage(Images.images[mapVector[c][(HEIGHT / 30) - 3]], c * 30,
					((HEIGHT / 30) - 3) * 30, null);
		}

		for (int c = 1; c < 7; c++) {
			g.drawImage(Images.images[mapVector[c][(HEIGHT / 30) - 2]], c * 30,
					((HEIGHT / 30) - 2) * 30, null);
			g.drawImage(Images.images[mapVector[c][(HEIGHT / 30) - 3]], c * 30,
					((HEIGHT / 30) - 3) * 30, null);
		}

		for (int c = (Math.round((WIDTH / 30) / 2)) - 3; c < (Math
				.round((WIDTH / 30) / 2)) + 3; c++) {
			g.drawImage(Images.images[mapVector[c][(HEIGHT / 30) - 2]], c * 30,
					((HEIGHT / 30) - 2) * 30, null);
			g.drawImage(Images.images[mapVector[c][(HEIGHT / 30) - 3]], c * 30,
					((HEIGHT / 30) - 3) * 30, null);
		}

		repaintStats(g);

		Iterator<Sprite> iterator = shots.iterator();
		while (iterator.hasNext()) {
			Sprite shott = iterator.next();
			int shotx = (int) Math.round(shott.getX() / 30);
			int shoty = (int) Math.round(shott.getY() / 30);
			for (int c = shotx - 2; c < shotx + 2; c++) {
				try {
					g.drawImage(Images.images[mapVector[c][shoty - 2]], c * 30,
							(shoty - 2) * 30, null);
				} catch (ArrayIndexOutOfBoundsException e) {
				}
				try {
					g.drawImage(Images.images[mapVector[c][shoty - 1]], c * 30,
							(shoty - 1) * 30, null);
				} catch (ArrayIndexOutOfBoundsException e) {
				}
				try {
					g.drawImage(Images.images[mapVector[c][shoty]], c * 30,
							shoty * 30, null);
				} catch (ArrayIndexOutOfBoundsException e) {
				}
				try {
					g.drawImage(Images.images[mapVector[c][shoty + 1]], c * 30,
							(shoty + 1) * 30, null);
				} catch (ArrayIndexOutOfBoundsException e) {
				}
				try {
					g.drawImage(Images.images[mapVector[c][shoty + 2]], c * 30,
							(shoty + 2) * 30, null);
				} catch (ArrayIndexOutOfBoundsException e) {
				}
			}
			shott.draw(g);
		}
	}
	
	/**
	 * Refreshes the game screen around a hitten object.
	 * @param g
	 * @param sprite
	 */
	public void refreshHittenObject(Graphics2D g, Sprite sprite) {
		int shotx = (int) Math.round(sprite.getX() / 30);
		int shoty = (int) Math.round(sprite.getY() / 30);
		for (int c = shotx - 1; c < shotx + 2; c++) {
			try {
				g.drawImage(Images.images[mapVector[c][shoty - 1]], c * 30,
						(shoty - 1) * 30, null);
			} catch (ArrayIndexOutOfBoundsException e) {
			}
			try {
				g.drawImage(Images.images[mapVector[c][shoty]], c * 30,
						shoty * 30, null);
			} catch (ArrayIndexOutOfBoundsException e) {
			}
			try {
				g.drawImage(Images.images[mapVector[c][shoty + 1]], c * 30,
						(shoty + 1) * 30, null);
			} catch (ArrayIndexOutOfBoundsException e) {
			}
		}
	}
	
	/**
	 * Is called if checkRound calculates a win a draw of a round.
	 * All player and shots will be reseted. 
	 * @param player
	 */
	public void newRound(List<Player> player) {
		Iterator<Player> iteratorPlayer = player.iterator();
		while (iteratorPlayer.hasNext()) {			
			Player player1 = iteratorPlayer.next();
			player1.setX(player1.getStartX());
			player1.setY(player1.getStartY());
			player1.setUp(false);
			player1.setDown(false);
			player1.setLeft(false);
			player1.setRight(false);
			player1.setStraferight(false);
			player1.setStrafeleft(false);
			player1.setShoot(false);
			player1.setHp(100);
			if (player1.getTeam() == 1) {
				player1.setAngle(180);
			} else {
				player1.setAngle(0);
			}
			player1.setRearm(false);
			player1.setFire(true);
			player1.reloadTime = 0.0;
		}
		shots.removeAll(shots);
		shots.clear();
		rearmAll(player);
		fB = false;
		dispose = 0;
		paintMap(g);		
	}
	
	/**
	 * The server could call this method with typing "cf_restard" to the chat.
	 * The game would be reseted to the beginning.
	 * @param player
	 */
	public void forceNewRound(List<Player> player){
		Iterator<Player> iteratorPlayer = player.iterator();
		while (iteratorPlayer.hasNext()) {
			shots.removeAll(shots);
			Player player1 = iteratorPlayer.next();
			player1.setX(player1.getStartX());
			player1.setY(player1.getStartY());
			player1.setUp(false);
			player1.setDown(false);
			player1.setLeft(false);
			player1.setRight(false);
			player1.setStraferight(false);
			player1.setStrafeleft(false);
			player1.setShoot(false);
			player1.setSpree(0);
			player1.setStatsKills(0);
			player1.setStatsDeaths(0);
			statsTeamBlau=0;
			statsTeamRot=0;
			player1.setHp(100);
			if (player1.getTeam() == 1) {
				player1.setAngle(180);
			} else {
				player1.setAngle(0);
			}
			player1.setRearm(false);
			player1.setFire(true);
			player1.reloadTime = 0.0;
		}
		shots.clear();
		rearmAll(player);		
		time = 3;
		fB = false;
		gameStop = false;
		gameStart = false;
		start=true;
		timeToNextRound = 0;
		timeToNextRoundHelp = false;
		dispose = 0;
		paintMap(g);
	}
	
	/**
	 * Rearms all players at the beginning of each round.
	 * @param player
	 */
	public void rearmAll(List<Player> player) {
		Iterator<Player> iteratorPlayer = player.iterator();
		while (iteratorPlayer.hasNext()) {
			Player player1 = iteratorPlayer.next();
			player1.setWeaponStuff(1, 1, 60);
			player1.setWeaponStuff(1, 2, 30);
			player1.setWeaponStuff(2, 1, 35);
			player1.setWeaponStuff(2, 2, 7);
			player1.setWeaponStuff(3, 1, 50);
			player1.setWeaponStuff(3, 2, 50);
			player1.setWeaponStuff(4, 1, 30);
			player1.setWeaponStuff(4, 2, 10);
		}
	}
	
	/**
	 * Paints the map on the game screen.
	 * @param g
	 */
	public void paintMap(Graphics2D g) {
		int k = 0;
		int l = 0;
		int m = 0;
		int n = 0;
		while (k < HEIGHT) {
			while (l < WIDTH) {
				g.drawImage(Images.images[mapVector[m][n]], k, l, null);
				l = l + 30;
				n++;
			}
			k = k + 30;
			l = 0;
			m++;
			n = 0;
		}
	}
	
	/**
	 * Plays the a sound if the weapon is empty and the player wants to shot.
	 * @param player
	 */
	public void playSound(Player player) {
		if (player.isKnife()) {
			soundCache.playSound(weaponSounds[player.getWeaponMode()]);
			player.setKnife(false);
		}
		if (player.isClick()) {
			soundCache.playSound(weaponSounds[6]);			
			player.setClick(false);
		}
	}
	
	/**
	 * Paints the game stats on the game screen. 
	 * @param g
	 */
	public void paintStats(Graphics2D g) {
		synchronized (players) {
			Composite oldC = g.getComposite();
			Font oldF = g.getFont();
			if (stats) {
				g.setComposite(AlphaComposite.getInstance(
						AlphaComposite.SRC_OVER, 0.70f));
				g.drawImage(new ImageIcon(getClass()
						.getResource(
								Einstellungen.getShooterImageFolderPath()
										+ "stats.png")).getImage(), 60, 60,
						null);
				g.setFont(new Font("Sans Serif", Font.BOLD, 20));
				g.setColor(Color.ORANGE);
				g.drawString("Score", 310, 90);
				g.drawString("Deaths", 385, 90);
//				g.drawString("Ping", 465, 90);
				g.setColor(Color.RED);
				g.drawString("WildBoys", 75, 120);
				g.drawString(Integer.toString(this.statsTeamRot), 332, 120);
				g.drawLine(75, 130, 525, 130);

				int k = 165;
				Iterator<Player> iteratorPlayer = players.iterator();
				while (iteratorPlayer.hasNext()) {
					Player player1 = iteratorPlayer.next();
					if (player1.getTeam() == 1) {
						g.drawString(player1.getName(), 75, k);
						g.drawString(Integer.toString(player1.getStatsKills()),
								332, k);
						g.drawString(
								Integer.toString(player1.getStatsDeaths()),
								413, k);
//						if(player1.getId()!= 0){
//							if(player1.getPing()<999){
//								g.drawString(Long.toString(player1.getPing()), 475, k);
//							}else {
//								g.drawString("999", 475, k);
//							}						
//						}else {
//							g.drawString("0", 475, k);
//						}											
						k = k + 30;
					}
				}

				k = k + 20;
				g.setColor(new Color(41, 129, 238));
				g.drawString("BulletProofs", 75, k);
				g.drawString(Integer.toString(this.statsTeamBlau), 332, k);
				g.drawLine(75, k + 10, 525, k + 10);

				k = k + 45;
				iteratorPlayer = players.iterator();
				while (iteratorPlayer.hasNext()) {
					Player player1 = iteratorPlayer.next();
					if (player1.getTeam() == 2) {
						g.drawString(player1.getName(), 75, k);
						g.drawString(Integer.toString(player1.getStatsKills()),
								332, k);
						g.drawString(
								Integer.toString(player1.getStatsDeaths()),
								413, k);
//						if(player1.getId()!= 0){
//							if(player1.getPing()<999){
//								g.drawString(Long.toString(player1.getPing()), 475, k);
//							}else {
//								g.drawString("999", 475, k);
//							}						
//						}else {
//							g.drawString("0", 475, k);
//						}
						k = k + 30;
					}
				}
			}
			g.setFont(oldF);
			g.setComposite(oldC);
		}
	}
	
	/**
	 * Repaints the game stats.
	 * @param g
	 */
	public void repaintStats(Graphics2D g) {
		int k = 60;
		int l = 60;
		int m = 2;
		int n = 2;
		while (k < 540) {
			while (l < 540) {
				g.drawImage(Images.images[mapVector[m][n]], k, l, null);
				l = l + 30;
				n++;
			}
			k = k + 30;
			l = 60;
			m++;
			n = 2;
		}
	}
	
	/**
	 * Draws a small green arrow over the player figure.
	 * @param player
	 * @param g
	 */
	public void drawPlayerArrow(Player player, Graphics2D g) {
		if (!player.isRearm()) {
			Composite oldC = g.getComposite();
			g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
					0.40f));
			g.drawImage(new ImageIcon(getClass().getResource(
					Einstellungen.getShooterImageFolderPath() + "pfeil.png"))
					.getImage(), ((int) player.getX()) + 5, ((int) player
					.getY()) - 22, null);
			g.setComposite(oldC);
		}
	}
	
	/**
	 * Calculates the current game state and returns a StateMessage.
	 * @return
	 */
	public StateMessage calculateState() {
		StateMessage ms = new StateMessage();

		playSound(players.get(playerIndex));

		List<Sprite> calcShots = new LinkedList<Sprite>();
		for (Sprite curr : this.shots) {
			try {
				calcShots.add((Sprite) curr.clone());
			} catch (CloneNotSupportedException e) {
				e.printStackTrace();
			}
		}
		// calcShots.addAll(shots);

		List<Player> calcPlayers = new LinkedList<Player>();
		for (Player curr : this.players) {
			try {
				calcPlayers.add((Player) curr.clone());
			} catch (CloneNotSupportedException e) {
				e.printStackTrace();
			}
		}
		// calcPlayers.addAll(players);

		List<Sprite> calcKisten = new LinkedList<Sprite>();
		calcKisten.addAll(kisten);
		
		List<Integer> calcClientShots = new LinkedList<Integer>();
		calcClientShots.addAll(clientShots);

		Iterator<Player> iteratorPlayer = calcPlayers.iterator();

		if (gameStop == true) {
			iteratorPlayer = calcPlayers.iterator();
			while (iteratorPlayer.hasNext()) {
				Player player = iteratorPlayer.next();
				player.move(30);
			}
		}
		
		if(collison){
			iteratorPlayer = calcPlayers.iterator();
			while (iteratorPlayer.hasNext()) {
				Player player = iteratorPlayer.next();
				dealWithCollision(player, calcPlayers, calcShots, calcKisten, g);
			}
		}		

		Iterator<Sprite> shotsIterator = calcShots.iterator();
		while (shotsIterator.hasNext()) {
			if (!sM) {
				shotsIterator.next().move(20);
			} else {
				shotsIterator.next().move(5);
			}
		}

		checkRound(calcPlayers);

		ms.setPlayers(calcPlayers);
		ms.setShots(calcShots);
		ms.setClientShots(calcClientShots);
		ms.setTimeToNextRoundHelp(timeToNextRoundHelp);
		if(crossServer!=null){
			ms.setTime(time);
			ms.setTimeToNextRound(timeToNextRound);
			ms.setfB(fB);
			ms.setStatsTeamBlau(statsTeamBlau);
			ms.setStatsTeamRot(statsTeamRot);
			ms.setCollision(collison);
		}		
		return ms;
	}
	
	/**
	 * Sets a calculated StateMessage.
	 * @param ms
	 */
	public void setState(StateMessage ms) {
		synchronized (players) {
			players.clear();
			players.addAll(ms.getPlayers());
			shots.clear();
			shots.addAll(ms.getShots());
			clientShots.clear();
			if(crossServer==null && ms.getTime()!=99){			
				this.time=ms.getTime();				
			}
			if(crossServer==null){
				this.timeToNextRound=ms.getTimeToNextRound();
				this.fB=ms.isfB();
				this.collison=ms.isCollision();
				this.timeToNextRoundHelp=ms.isTimeToNextRoundHelp();
				this.statsTeamRot=ms.getStatsTeamRot();
				this.statsTeamBlau=ms.getStatsTeamBlau();
				Iterator<Integer> shotsSoundIterator = ms.getClientShots().iterator();
				while (shotsSoundIterator.hasNext()) {
					int i = shotsSoundIterator.next();
					soundCache.playSound(weaponSounds[i]);
				}
			}			
		}				
	}
	
	/**
	 * Sets a MovementMessage form a client.
	 * @param mM
	 */
	public void setMovementState(MovementMessage mM){
		synchronized (players) {
			plist.get(mM.getPlayerIndex()).setUp(mM.isUp());
			plist.get(mM.getPlayerIndex()).setDown(mM.isDown());
			plist.get(mM.getPlayerIndex()).setLeft(mM.isLeft());
			plist.get(mM.getPlayerIndex()).setRight(mM.isRight());
			plist.get(mM.getPlayerIndex()).setStrafeleft(mM.isStrafeLeft());
			plist.get(mM.getPlayerIndex()).setStraferight(mM.isStrafeRight());
			plist.get(mM.getPlayerIndex()).setShoot(mM.isShoot());	
			plist.get(mM.getPlayerIndex()).setWeaponMode(mM.getWeaponMode());
			plist.get(mM.getPlayerIndex()).setRearm(mM.isReload());
		}
	}
	
//	public void setPlayerPing(PingMessage pM) {
//		synchronized (players) {
//			pings[pM.getPlayerIndex()][1] = System.currentTimeMillis()-pingStart;
//		}			
//	}
	
	/**
	 * Creates a new wall object.
	 */
	public void newWall(Wall wall) {
		this.kisten.add(wall);
	}
	
	/**
	 * Creates a new player object.
	 * @param player
	 */
	public void newPlayer(Player player) {
		synchronized (players) {
			this.players.add(player);
		}
	}
	
	/**
	 * Returns the row count of a map vector.
	 * @return
	 */
	public int getRowCount() {
		return rowCount;
	}
	
	/**
	 * Sets the row count of a map vector.
	 * @param rowCount
	 */
	public void setRowCount(int rowCount) {
		this.rowCount = rowCount;
	}
	
	/**
	 * Returns the height of the gaming screen.
	 * @return
	 */
	public int getHEIGHT() {
		return HEIGHT;
	}
	
	/**
	 * Sets the height of the gaming screen.
	 * @param height
	 */
	public void setHEIGHT(int height) {
		HEIGHT = height;
	}
	
	/**
	 * Returns the width of the gaming screen.
	 * @return
	 */
	public int getWIDTH() {
		return WIDTH;
	}
	
	/**
	 * Sets the width of the gaming screen.
	 * @param width
	 */
	public void setWIDTH(int width) {
		WIDTH = width;
	}
	
	/**
	 * Returns true if the game is running.
	 * @return
	 */
	public boolean isGame() {
		return game;
	}

	/**
	 * Sets the variable whether the game should run or not.
	 * @param game
	 */
	public void setGame(boolean game) {
		this.game = game;
	}
	
	/**
	 * Returns true if the stats are displayed.
	 * @return
	 */
	public boolean isStats() {
		return stats;
	}
	
	/**
	 * Sets the variable whether the stats should be displayed or not.
	 * @param stats
	 */
	public void setStats(boolean stats) {
		this.stats = stats;
	}
	
	/**
	 * Returns the Graphics object.
	 * @return
	 */
	public Graphics2D getG() {
		return g;
	}
	
	/**
	 * Sets the Graphics object.
	 * @param g
	 */
	public void setG(Graphics2D g) {
		this.g = g;
	}
	
	/**
	 * Returns the stat count of team red.
	 * @return
	 */
	public int getStatsTeamRot() {
		return statsTeamRot;
	}
	
	/**
	 * Sets the stat count of team red.
	 * @param statsTeamRot
	 */
	public void setStatsTeamRot(int statsTeamRot) {
		this.statsTeamRot = statsTeamRot;
	}
	
	/**
	 * Returns the stat count of team blue.
	 * @return
	 */
	public int getStatsTeamBlau() {
		return statsTeamBlau;
	}
	
	/**
	 * Sets the stat count of team blue.
	 * @param statsTeamBlau
	 */
	public void setStatsTeamBlau(int statsTeamBlau) {
		this.statsTeamBlau = statsTeamBlau;
	}

	/**
	 * Returns true if the game is in the freeze phase of a gaming round.
	 * @return
	 */
	public boolean isGameStop() {
		return gameStop;
	}
	
	/**
	 * Sets the variable whether the player should freeze.
	 * @param gameStop
	 */
	public void setGameStop(boolean gameStop) {
		this.gameStop = gameStop;
	}
	
	/**
	 * Returns true if Schneeballmodus is activated.
	 * @return
	 */
	public boolean isSM() {
		return sM;
	}
	
	/**
	 * Sets the Schneeballmodus true or false.
	 * @param sm
	 */
	public void setSM(boolean sm) {
		sM = sm;
	}
	
	/**
	 * Returns the list of all players.
	 * @return
	 */
	public Object getLock() {
		return this.players;
	}
	
	/**
	 * Returns the player with the index index.
	 * @param index
	 * @return
	 */
	public Player getPlayer(int index) {
		return this.players.get(index);
	}
}
